package digital_cash_system.bank;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;

import digital_cash_system.Logger;

public abstract class BankBase
{
	public final static String BankAddr = "localhost";
	public final static int Port = 7777;

	public static enum RequestType
	{
		Deposit, OpenAccount, Withdraw,
	}

	protected ServerSocket serverSocket;

	public BankBase()
	{

		try
		{
			serverSocket = new ServerSocket(Port);
			// --- Logger output
			Logger.getInstance().write("Listening for connections");
			// ---

		} catch (IOException e)
		{
			System.out.println(e);
		}

		ClientListener clientListener = new ClientListener();
		Thread thread = new Thread(clientListener);
		thread.start();
	}

	protected abstract void onDeposit(Socket clientSocket, ObjectInputStream inputStream);

	protected abstract void onOpenAccount(Socket clientSocket, ObjectInputStream inputStream);

	protected abstract void onWithdraw(Socket clientSocket, ObjectInputStream inputStream);

	protected void clientAppeared(Socket client)
	{
		ClientService clientService = new ClientService(client);
		Thread thread = new Thread(clientService);
		thread.start();
	}

	protected class ClientListener implements Runnable
	{
		@Override
		public void run()
		{
			while (true)
			{
				try
				{
					Socket clientSocket = serverSocket.accept();
					// --- Logger output
					Logger.getInstance().write("Connection received");
					// ---
					clientAppeared(clientSocket);
				} catch (IOException e)
				{
					e.printStackTrace();
				}
			}
		}
	}

	protected class ClientService implements Runnable
	{
		private Socket clientSocket;

		public ClientService(Socket clientSocket)
		{
			this.clientSocket = clientSocket;
		}

		@Override
		public void run()
		{
			ObjectInputStream input = null;
			RequestType requestType = null;
			try
			{
				input = new ObjectInputStream(clientSocket.getInputStream());
				requestType = (RequestType) input.readObject();
			} catch (ClassNotFoundException | IOException e)
			{
				e.printStackTrace();
			}

			// --- Logger output
			Logger.getInstance().write("requested " + requestType);
			// ---

			switch (requestType)
			{
			case Deposit:
				onDeposit(clientSocket, input);
				break;
			case OpenAccount:
				onOpenAccount(clientSocket, input);
				break;
			case Withdraw:
				onWithdraw(clientSocket, input);
				break;
			}
		}
	}
}
